package com.sh.rbac.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sh.rbac.domain.converter.MenuConverter;
import com.sh.rbac.domain.dto.menu.MenuQueryDTO;
import com.sh.rbac.domain.dto.menu.MenuSaveDTO;
import com.sh.rbac.domain.dto.menu.MenuUpdateDTO;
import com.sh.rbac.domain.entity.Menu;
import com.sh.rbac.domain.entity.User;
import com.sh.rbac.domain.enums.UserTypeEnum;
import com.sh.rbac.domain.vo.menu.MenuNavVO;
import com.sh.rbac.exception.CustomException;
import com.sh.rbac.mapper.MenuMapper;
import com.sh.rbac.result.ResultCodeEnum;
import com.sh.rbac.service.MenuService;
import com.sh.rbac.utils.SecurityHolderUtils;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author lucky
 * @description 针对表【sys_menu(菜单表)】的数据库操作Service实现
 * @createDate 2024-04-04 21:47:19
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu>
        implements MenuService {

    @Override
    public List<MenuNavVO> getMenus() {
        // 获取用户信息
        User user = SecurityHolderUtils.getUser();

        List<Menu> menus = baseMapper.getMenusByUserId(UserTypeEnum.isAdmin(user.getUsertype()) ? null : user.getId());

        return formatMenuNav(menus, 0L);
    }

    @Override
    public List<Menu> getList(MenuQueryDTO menuQueryDTO) {
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(menuQueryDTO.getMenuName()), Menu::getMenuName, menuQueryDTO.getMenuName());
        wrapper.eq(menuQueryDTO.getStatus() != null, Menu::getStatus, menuQueryDTO.getStatus());
        wrapper.orderByAsc(Menu::getPriority);

        List<Menu> menus = baseMapper.selectList(wrapper);
        return this.findMenu(menus, 0L);
    }

    @Override
    public Boolean save(MenuSaveDTO menuSaveDTO) {
        Menu menu = MenuConverter.INSTANCE.toEntity(menuSaveDTO);
        return super.save(menu);
    }

    @Override
    public Boolean updateById(MenuUpdateDTO menuUpdateDTO) {
        Menu menu = MenuConverter.INSTANCE.toEntity(menuUpdateDTO);
        return super.updateById(menu);
    }

    @Override
    public Boolean updateStatus(Long id, Integer status) {
        Menu menu = new Menu();
        menu.setId(id);
        menu.setStatus(status);

        return super.updateById(menu);
    }

    @Override
    public Set<String> getAuth() {
        User user = SecurityHolderUtils.getUser();
        Long userId = UserTypeEnum.isAdmin(user.getUsertype()) ? null : user.getId();

        return new HashSet<>(baseMapper.getPermissionByUserId(userId));
    }

    @Override
    public boolean removeById(Serializable id) {
        List<Menu> menus = baseMapper.selectList(new LambdaQueryWrapper<Menu>().eq(Menu::getParentId, id));
        if (!menus.isEmpty()) {
            throw new CustomException(ResultCodeEnum.NODE_HAS_CHILDREN);
        }
        return super.removeById(id);
    }

    @Override
    public boolean removeBatchByIds(Collection<?> list) {
        try {
            list.forEach(id -> super.removeById((Serializable) id));
        } catch (Exception e) {
            return false;
        }
        return super.removeBatchByIds(list);
    }

    /**
     * 递归查询菜单
     *
     * @param menus    菜单集合
     * @param parentId 父节点ID
     * @return 菜单集合
     */
    private List<Menu> findMenu(List<Menu> menus, Long parentId) {
        return menus.stream()
                // 筛选父节点
                .filter(menu -> menu.getParentId().equals(parentId))
                // 递归查询子节点
                .peek(menu -> {
                    List<Menu> children = findMenu(menus, menu.getId());
                    menu.setChildren(children);
                    menu.setHasChildren(children == null);
                })
                // 收集数据转换为列表
                .collect(Collectors.toList());
    }


    /**
     * 格式化菜单导航
     *
     * @param menus    菜单
     * @param parentId 父节点ID
     * @return 菜单导航视图集合
     */
    private List<MenuNavVO> formatMenuNav(List<Menu> menus, Long parentId) {
        return menus.stream().filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> {
                    MenuNavVO menuNavVO = new MenuNavVO();
                    menuNavVO.setName(StrUtil.upperFirst(menu.getPath()));
                    menuNavVO.setPath(menu.getPath());
                    menuNavVO.setComponent(menu.getComponent());
                    menuNavVO.setRedirect(menu.getRedirect());
                    menuNavVO.setHidden(menu.getVisible() == 1);
                    MenuNavVO.Meta mate = new MenuNavVO.Meta();
                    mate.setTitle(menu.getMenuName());
                    mate.setIcon(menu.getIcon());
                    menuNavVO.setMeta(mate);
                    menuNavVO.setChildren(formatMenuNav(menus, menu.getId()));
                    return menuNavVO;
                }).collect(Collectors.toList());
    }

}




